package com.cheval.rpcframe.handler;

import com.cheval.rpcframe.register.LocalRegister;
import org.apache.log4j.Logger;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;

public class RemoteInvokeHandler implements Handler {

    private Logger logger = Logger.getLogger(RemoteInvokeHandler.class);

    @Override
    public void handle(HandlerContext handlerContext, HttpServletResponse response) {
        if (handlerContext.invocation == null) {
            logger.error("消息中无调用信息，不处理");
            return;
        }

        try {
            ServletOutputStream outputStream = response.getOutputStream();
            String interfaceClassName = handlerContext.invocation.getInterfaceClassName();
            String invokedMethodName = handlerContext.invocation.getInvokedMethodName();
            Class[] argsTypes = handlerContext.invocation.getArgsTypes();
            Object[] args = handlerContext.invocation.getArgs();
            String version = handlerContext.invocation.getVersion();

            // 获取实现类
            Class<?> aClass = LocalRegister.get(interfaceClassName, version);
            if (aClass == null) {
                String msg = "没有找到【" + interfaceClassName + "】的实现类";
                logger.error(msg);
                outputStream.write(msg.getBytes(StandardCharsets.UTF_8));
                outputStream.flush();
                return;
            }

            // 调用并返回结果
            Method method = aClass.getMethod(invokedMethodName, argsTypes);
            Object result = method.invoke(aClass.newInstance(), args);
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(result);
            oos.flush();
            outputStream.write(bos.toByteArray());
            outputStream.flush();
            oos.close();
            bos.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
